<?php
/**
 * Created by PhpStorm.
 * User: pengzhizhuang
 * Date: 17/5/26
 * Time: 上午11:10
 */

namespace App\Http\Traits;

use App\Models\Finance\Paygate;
use App\Models\Order\Order;
use App\Models\Order\OrderLog;
use App\Models\Order\OrderRepair;
use App\Services\Message\NoticeService;
use App\Services\Tmall\OrderService;
use Omnipay\Omnipay;

trait RefundTrait
{

    /**
     * @param $vendor
     * @param $repairId
     * @return \Illuminate\Http\RedirectResponse|string
     * 退货退款操作
     */
    public function orderRepairRefund($vendor, $repairId)
    {
        $repair = OrderRepair::find($repairId);
        if (empty($repair)) {
            return ['status' => 0, 'message' => '该退货订单不存在'];
        }

        $log = OrderLog::where('order_id', $repair->order_id)->where('type', 0)->first();
        if (empty($log)) {
            return ['status' => 0, 'message' => '该订单交易记录不存在'];
        }
        //订单总金额
        $repair->all_price = $repair->order->price;
        //订单第三方交易号
        $repair->trans_no = $log->trans_no;
        if (!empty($repair->options->reason)) {
            $repair->reason = $repair->options->reason;
        }

        return $this->refund($vendor, $repair, 'repair');
    }

    /**
     * @param $vendor
     * @param $orderId
     * @return array
     * 订单取消退款操作
     */
    public function orderCancelRefund($vendor, $orderId)
    {
        $order = Order::find($orderId);
        if (empty($order)) {
            return ['status' => 0, 'message' => '该订单不存在'];
        }

        $log = OrderLog::where('order_id', $order->id)->where('type', 0)->first();
        if (empty($log)) {
            return ['status' => 0, 'message' => '该订单交易记录不存在'];
        }
        //订单总金额
        $order->all_price = $order->price;
        //订单交易号
        $order->trans_no = $log->trans_no;
        $order->order_sn = $order->order_no;

        return $this->refund($vendor, $order, 'cancel');
    }

    /**
     * @param $vendor
     * @param $data
     * @param $source
     * @return array
     * 退款入口
     */
    private function refund($vendor, $data, $source)
    {
        $config = $this->getPayConfig($vendor);
        if (empty($config)) {
            return ['status' => 0, 'message' => '配置错误'];
        }

        try {
            $func = 'get' . ucfirst($vendor) . 'Gateway';
            $gateway = $this->{$func}($config);
            $rdata = $this->getRefundData($data, $vendor);
            $response = $gateway->refund($rdata)->send();
            $func = $vendor . 'Refund';
            return $this->{$func}($source, $response, $data);
        } catch (\Exception $e) {
            if ($vendor == 'wechatpay') {
                return ['status' => 0, 'message' => '请检查微信支付配置数据或证书错误'];
            }
            return ['status' => 0, 'message' => '请检查支付宝支付配置数据是否有误'];
        }
    }

    /**
     * @param $response
     * @param $repair
     * 支付宝退款
     */
    private function alipayRefund($source, $response, $data)
    {
        $redirectUrl = $response->getRedirectUrl();
        $service = new OrderService();
        $options = (array)simplexml_load_string(file_get_contents($redirectUrl), 'SimpleXMLElement', LIBXML_NOCDATA);
        if (!empty($options['is_success']) && $options['is_success'] == 'T') {
            if ($source == 'repair') {
                $sdata = [
                    'repair_id' => $data->id,
                    'vendor' => 'alipay',
                    'order_id' => $data->order_id,
                    'order_no' => $data->order_sn,
                ];

                $service->setPaidRepair($sdata);

                $this->repairSendTo($data);
            }
            if ($source == 'cancel') {
                $sdata['order_id'] = $data->id;
                $sdata['vendor'] = 'alipay';
                $service->setPaidOrderCancel($sdata);
            }
            return ['status' => 1, 'message' => '退款成功'];
        }
        return ['status' => 0, 'message' => '退款失败'];
    }

    /**
     * @param $response
     * @param $repair
     * 微信退款
     */
    private function wechatpayRefund($source, $response, $data)
    {
        $service = new OrderService();
        if ($response->isSuccessful()) {
            $options = $response->getData();
            error_log(var_export($options, true), 3, '/tmp/refund.log');
            if (!empty($options['result_code']) && $options['result_code'] == 'SUCCESS') {
                if ($source == 'repair') {
                    $sdata = array_merge(
                        $options, [
                        'repair_id' => $data->id,
                        'vendor' => 'wechatpay',
                        'order_id' => $data->order_id,
                        'order_no' => $data->order_sn,
                        ]
                    );
                    $service->setPaidRepair($sdata);
                    $this->repairSendTo($data);
                }
                if ($source == 'cancel') {
                    $sdata = array_merge(
                        $options, [
                        'order_id' => $data->id,
                        'vendor' => 'wechatpay',
                        ]
                    );
                    $service->setPaidOrderCancel($sdata);
                }
                return ['status' => 1, 'message' => '退款成功'];
            }
        }
        return ['status' => 0, 'message' => '退款失败'];
    }

    /**
     * @param $repair
     * 退款成功发送消息
     */
    private function repairSendTo($repair)
    {
        $service = new NoticeService();
        if (!empty($repair)) {
            $sdata = [
                'tenant_id' => $repair->tenant_id,
                'order_no' => $repair->order_sn,
                'time' => time(),
                'user_id' => $repair->customer_id,
                'mobile' => $repair->user->mobile,
                'email' => $repair->user->email,
                'type' => 'refund_goods_money',
            ];
            $service->operateSend($sdata);
        }
    }

    /**
     * @param $repairData
     * @param $vendor
     * @return mixed
     *
     * 退款记录
     */
    private function getRefundData($repairData, $vendor)
    {
        return call_user_func_array(array($this, "get" . ucfirst($vendor) . 'Data'), array($repairData));
    }

    /**
     * @param $key
     * @return array
     * 获取支付配置信息
     */
    private function getPayConfig($key)
    {
        $tenantId = getTenantId();
        $paygate = Paygate::where('tenant_id', $tenantId)->where('key', $key)->where('status',1)->first();
        if (!empty($paygate)) {
            return $paygate->options;
        }
        return [];
    }

    /**
     * @param $config
     * @return mixed
     * 获取支付宝网关
     */
    private function getAlipayGateway($config)
    {
        $sellerEmail = !empty($config['sellerEmail']) ? $config['sellerEmail'] : '';
        $partner = !empty($config['partner']) ? $config['partner'] : '';
        $key = !empty($config['key']) ? $config['key'] : '';
        $gateway = Omnipay::create('Alipay_LegacyExpress');
        $gateway->setSellerEmail($sellerEmail);
        $gateway->setPartner($partner);
        $gateway->setKey($key);
        $gateway->setNotifyUrl(url('refund/notify/alipay'));
        return $gateway;
    }

    /**
     * @param $config
     * @return mixed
     * 获取微信支付网关
     */
    private function getWechatpayGateway($config)
    {
        $appId = !empty($config['appId']) ? $config['appId'] : '';
        $mchId = !empty($config['mchId']) ? $config['mchId'] : '';
        $apiKey = !empty($config['apiKey']) ? $config['apiKey'] : '';
        $certPath = !empty($config['certPath']) ? $config['certPath'] : '';
        $keyPath = !empty($config['keyPath']) ? $config['keyPath'] : '';
        $gateway = Omnipay::create('WechatPay_Native');
        $gateway->setAppId($appId);
        $gateway->setMchId($mchId);
        $gateway->setApiKey($apiKey);
        $gateway->setCertPath($certPath);
        $gateway->setKeyPath($keyPath);
        $gateway->setNotifyUrl(url('refund/notify/wechatpay'));
        return $gateway;
    }

    /**
     * @param $config
     * @return mixed
     * 获取银联在线支付网关
     */
    private function getUnionpayGateway($config)
    {
        $merId = !empty($config['merId']) ? $config['merId'] : '';
        $certPath = !empty($config['certPath']) ? $config['certPath'] : '';
        $certPassword = !empty($config['certPassword']) ? $config['certPassword'] : '';
        $certDir = !empty($config['certDir']) ? $config['certDir'] : '';
        $gateway = Omnipay::create('UnionPay_Express');
        $gateway->setMerId($merId);
        $gateway->setEnvironment('production');
        $gateway->setCertPath($certPath);
        $gateway->setCertPassword($certPassword);
        $gateway->setCertDir($certDir);
        $gateway->setNotifyUrl(url('refund/notify/unionpay'));
        return $gateway;
    }

    /**
     * @param $orderData
     * @return array
     * 获取支付宝发送数据
     */
    private function getAlipayData($refundData)
    {
        return [
            'refund_items' => [
                [
                    'out_trade_no' => $refundData['trans_no'],
                    'amount' => $refundData['price'],
                    'reason' => !empty($refundData['reason']) ? $refundData['reason'] : '退款',
                ]
            ]
        ];
    }

    /**
     * @param $orderData
     *
     * 获取银联支付数据
     */
    private function getUnionpayData($refundData)
    {
        return [
            'orderId' => !empty($refundData['repair_no']) ? $refundData['repair_no'] : date('YmdHis'),
            'queryId' => $refundData['trans_no'],
            'txnTime' => date('YmdHis'),
            'txnAmt' => $refundData['price'] * 100,
        ];
    }

    /**
     * @param $orderData
     *
     * 获取微信支付数据
     */
    private function getWechatpayData($refundData)
    {
        return [
            'transaction_id' => $refundData['trans_no'],
            'out_refund_no' => !empty($refundData['repair_no']) ? $refundData['repair_no'] : date('YmdHis'),
            'out_trade_no' => $refundData['order_sn'],
            'total_fee' => $refundData['all_price'] * 100,
            'refund_fee' => $refundData['price'] * 100,
        ];
    }
}
